<template>
  <div class="body_style">
    <PageTitle>
      <template slot="left">css3 Shadow实现图片</template>
      <template slot="right">
        <a-button class="btn_margin" @click="downloadFile">下载代码</a-button>
      </template>
    </PageTitle>
    <div class="content_box padding_box box_border">
      <div class="content_area">
        <div class="show_area">
          <div class="herf_area">
            <UploadFile @getFile="getFile">
              <div class="upload_area">
                <a-icon class="icon_style" type="plus" />
                <div class="tip">
                  * 请注意可能提交的图片颜色过于复杂，所以采取下载方式获取代码
                </div>
              </div>
            </UploadFile>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import PageTitle from "@/components/pageTitle/index.vue";
import UploadFile from "@/components/uploadFile/index.vue";
import { downloadHtml } from "@/utils/util";
export default {
  name: "imageShadow",
  components: { PageTitle, UploadFile },
  data() {
    return {
      fileHtml: "",
    };
  },
  methods: {
    async getFile(file) {
      const img = await this.loadImage(file); // 得到图片对象
      if (!img) {
        return;
      }
      // 将图片画到 canvas 上
      const cvs = document.createElement("canvas");
      cvs.width = img.width;
      cvs.height = img.height;
      const ctx = cvs.getContext("2d");
      ctx.drawImage(img, 0, 0);

      // 获取 canvas 中的位图
      const bmp = ctx.getImageData(0, 0, img.width, img.height).data;
      this.fileHtml = this.createHTML(img.width, img.height, bmp);
    },

    downloadFile() {
      if (this.fileHtml) {
        this.$toast("因为渲染的代码长度可能过长，以下载文件方式获取代码");
        setTimeout(() => {
          downloadHtml(this.fileHtml);
        }, 300);
      } else {
        this.$toast.fail("请先上传图片");
      }
    },

    // 根据选择的文件生成图片对象
    loadImage(file) {
      const objUrl = URL.createObjectURL(file);
      const img = new Image();
      return new Promise((resolve, reject) => {
        img.onload = () => {
          resolve(img);
        };
        img.onerror = () => {
          resolve(null);
        };
        img.src = objUrl;
      });
    },

    createHTML(width, height, bmp) {
      const shadowCSSFragments = []; // 阴影 css 的片段
      const shadowCSSHover = []; // 鼠标移入的 css 阴影
      // 读取每个位图的像素点
      for (let r = 0; r < height; r++) {
        for (let c = 0; c < width; c++) {
          const i = r * width + c;
          const R = bmp[i * 4],
            G = bmp[i * 4 + 1],
            B = bmp[i * 4 + 2],
            A = bmp[i * 4 + 3] / 255;
          shadowCSSFragments.push(
            `${c + 1}px ${r}px rgba(${R},${G},${B},${A})`
          );
          shadowCSSHover.push(
            `${c + 1}px ${r}px rgba(${255 - R},${255 - G},${255 - B},${A})`
          );
        }
      }
      return `
  <!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <style>
        .shadow-img{
            width: ${width}px;
            height: ${height}px;
        }
        .shadow-img .inner{
            width:1px;
            height:1px;
            box-shadow: ${shadowCSSFragments.join(",")};
            transition: 1.5s;
        }
        .shadow-img:hover .inner{
            box-shadow: ${shadowCSSHover.join(",")};
        }
    </style>
  </head>
  <body>
    <div class="shadow-img">
        <div class="inner"></div>
    </div>
  </body>
</html>
  `;
    },
  },
};
</script>

<style lang="less" scoped>
.btn_margin {
  margin: 0 20px;
}
.body_style {
  display: flex;
  flex-direction: column;
  height: 100%;

  .content_box {
    flex: 1;
    background-color: #fff;

    .content_area {
      height: 100%;
      overflow-y: scroll;
    }
  }
}

.show_area {
  display: flex;

  .herf_area {
    height: 500px;
    width: 100%;
    border-radius: 8px;
    overflow: hidden;
    border: 1px dashed #dad0d0;
  }
}

.upload_area {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  width: 100%;
  height: 100%;
  .icon_style {
    font-size: 64px;
  }
  .tip {
    margin-top: 100px;
    font-size: 16px;
    font-weight: 800;
    color: red;
  }
}
</style>
